package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrderMapper;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;

    /**
     * 用户下单
     *
     * @param orders
     */
    @Override
    @Transactional   //涉及操作多个表，开启事务管理
    public void submit(Orders orders) {
        //获得当前用户Id
        Long userId = BaseContext.getCurrentId();

        //查询当前用户的购物车数据
        LambdaQueryWrapper<ShoppingCart> shoppingCartLWQ = new LambdaQueryWrapper<>();
        shoppingCartLWQ.eq(ShoppingCart::getUserId, userId);
        List<ShoppingCart> shoppingCartList = shoppingCartService.list(shoppingCartLWQ);

        //加入对购物车数据为空的判断
        if (shoppingCartList == null || shoppingCartList.size() == 0) {
            throw new CustomException("购物车为空，下单失败");
        }

        //查询用户数据
        User user = userService.getById(userId);
        //查询地址数据
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        //加入对地址信息为空的判断
        if (addressBook == null) {
            throw new CustomException("地址信息为空，下单失败");
        }

        //MP提供的ID生成器，工具类
        long orderId = IdWorker.getId();

        //AtomicInteger amount = new AtomicInteger(0);
        BigDecimal amount = new BigDecimal(0);
        /*
         * AtomicInteger是jdk提供了JUC（java.util.concurrent java并发包）提供的原子类
         *    AtomicInteger原子类 内部使用乐观锁解决并发线程安全。乐观锁是可以并发，性能会好一些（竞争小性能好，竞争大性能差）
         *          多个线程运行竞争一个竞争点，运行最快的线程优先成功，其他线程会使其失败，失败的线程会重新运行,
         *          直至成功。所以在竞争大（就是线程数过大）的时候会造成大量失败重试，导致CPU飙高崩溃。
         *    java的synchronized 是悲观锁，不能并发，性能慢。
         *    LongAddr jdk8提供的，阿里巴巴最推荐使用计数器（加减操作）。
         *       原子类和synchronized都是一个竞争点的竞争，LongAddr可以根据线程的数量自动设置多个竞争点，
         *       LongAddr确保一个竞争点上的线程数量不会过大，从而保证每个竞争点的性能高效。（避免了大量线程失败重试）
         * */

      /*  //组装订单明细信息
        List<OrderDetail> orderDetails = shoppingCartList.stream().map((item) -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setNumber(item.getNumber());
            orderDetail.setDishFlavor(item.getDishFlavor());
            orderDetail.setDishId(item.getDishId());
            orderDetail.setSetmealId(item.getSetmealId());
            orderDetail.setName(item.getName());
            orderDetail.setImage(item.getImage());
            orderDetail.setAmount(item.getAmount());
            // 计算公式: 菜品的金额 乘以(multiply) 分数
            amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
            return orderDetail;
        }).collect(Collectors.toList());*/

        //组装订单明细信息
        List<OrderDetail> orderDetails = new ArrayList<>();
        for (ShoppingCart item : shoppingCartList) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            // orderDetail.setNumber(item.getNumber());
            // orderDetail.setDishFlavor(item.getDishFlavor());
            // orderDetail.setDishId(item.getDishId());
            // orderDetail.setSetmealId(item.getSetmealId());
            // orderDetail.setName(item.getName());
            // orderDetail.setImage(item.getImage());
            // orderDetail.setAmount(item.getAmount());
            BeanUtils.copyProperties(item, orderDetail);
            amount = amount.add(item.getAmount().multiply(new BigDecimal(item.getNumber())));

            orderDetails.add(orderDetail);
        }

        //组装订单数据
        orders.setId(orderId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setStatus(1);        // 1：表示待付款    2：表示待派送
//        orders.setAmount(new BigDecimal(amount.get()));//总金额
        orders.setAmount(amount);//总金额
        orders.setUserId(userId);
        orders.setNumber(String.valueOf(orderId));
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        //向订单表插入数据，一条数据
        this.save(orders);


        //向订单明细表插入数据，多条数据
        orderDetailService.saveBatch(orderDetails);

        //清空购物车数据
        shoppingCartService.remove(shoppingCartLWQ);
    }
}